#ifndef __LABOR_STRINGENCODING_H__
#define __LABOR_STRINGENCODING_H__
#include "../LaborCoreDef.h"
#include <wchar.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
namespace XmlParser{
	template<int _WCharWidth> class TWCharTrait
	{
	public:
		typedef wchar_t        CharType ;
		typedef wchar_t        UTF32;
		typedef unsigned short UTF16;
		typedef unsigned char  UTF8;
		enum { WCharWidth = _WCharWidth , }; 

	public:
		wchar_t  GetCodePoint(const wchar_t* _text , size_t& index , wchar_t* _out);
		wchar_t  GetCodePoint(const wchar_t* _text , size_t& index );
		size_t   strlen(const wchar_t* _text);
	};


#ifdef _WIN32
	typedef unsigned __int32 xint32_u;
#else
	typedef unsigned int     xint32_u;
#endif

	template<> class TWCharTrait<2>
	{
	public:
		typedef unsigned int   CharType ;
		typedef wchar_t        UTF16;
		typedef xint32_u       UTF32;
		typedef unsigned char  UTF8;

		enum { WCharWidth = 2 , } ; 
	public:
		UTF32  GetCodePoint(const wchar_t* _text , size_t& index , wchar_t* _out);
		UTF32  GetCodePoint(const wchar_t* _text , size_t& index );
		size_t strlen(const wchar_t* _text);
	};




	typedef TWCharTrait<sizeof(wchar_t)>           xWCharTrait;
	typedef xWCharTrait::CharType                  xWCharType; 

	typedef xWCharTrait::UTF32  UTF32;	/* at least 32 bits */
	typedef xWCharTrait::UTF16  UTF16;	/* at least 16 bits */
	typedef xWCharTrait::UTF8   UTF8;	/* typically 8 bits */

	/* Some fundamental constants */
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
#define UNI_MAX_BMP (UTF32)0x0000FFFF
#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF

	typedef enum 
	{
		conversionOK, 		/* conversion successful */
		sourceExhausted,	/* partial character in source, but hit end */
		targetExhausted,	/* insuff. room in target for conversion */
		sourceIllegal,		/* source sequence is illegal/malformed */
		conversionFailed,
	} ConversionResult;

	typedef enum 
	{
		strictConversion = 0,
		lenientConversion
	} ConversionFlags;


	ConversionResult XEvol_Utf8ToUtf16 (const UTF8*  sourceStart,  UTF16* targetStart , size_t outlen , ConversionFlags flags = lenientConversion);
	ConversionResult XEvol_Utf16ToUtf8 (const UTF16* sourceStart,  UTF8* targetStart  , size_t outlen , ConversionFlags flags = lenientConversion);
	ConversionResult XEvol_Utf8ToUtf32 (const UTF8*  sourceStart,  UTF32* targetStart , size_t outlen , ConversionFlags flags = lenientConversion);
	ConversionResult XEvol_Utf32ToUtf8 (const UTF32* sourceStart,  UTF8* targetStart  , size_t outlen , ConversionFlags flags = lenientConversion);
	ConversionResult XEvol_Utf16ToUtf32(const UTF16* sourceStart,  UTF32* targetStart , size_t outlen , ConversionFlags flags = lenientConversion);
	ConversionResult XEvol_Utf32ToUtf16(const UTF32* sourceStart,  UTF16* targetStart , size_t outlen , ConversionFlags flags = lenientConversion);
	ConversionResult XEvol_UnicodeToFsEnc(const wchar_t* _in, char* _out,size_t outlen);
	ConversionResult XEvol_FsEncToUnicode(const char* _in, wchar_t* _out,size_t outlen);
	ConversionResult XEvol_Utf8ToUnicode(const char* _in, wchar_t* _out,size_t outlen);
	ConversionResult XEvol_UnicodeToUtf8(const wchar_t* _in, char* _out,size_t outlen);
	ConversionResult XEvol_LocaleToUtf8(const char* _in, char* _out,size_t outlen);
	ConversionResult XEvol_Utf8ToLocale(const char* _in, char* _out,size_t outlen);
	ConversionResult XEvol_UnicodeToLocale(const wchar_t* _in, char* _out,size_t outlen);
	ConversionResult XEvol_LocaleToUnicode(const char* _in, wchar_t* _out,size_t outlen);
	UTF32            XEvol_GetUtf32CodePoint(const UTF16 * text , size_t &c , UTF16 * strOut);
	bool             XEvol_IsUtf8(const UTF8 * source, const UTF8 *sourceEnd);
	size_t           XEvol_UTF16Len(const UTF16 * text);
	const wchar_t*   XEvol_LocaleToUnicode(const char* _in);
	const char*      XEvol_UnicodeToLocale(const wchar_t* _in);

	const wchar_t*   XEvol_LocaleToUnicode(const char* _in);
	const char*      XEvol_UnicodeToLocale(const wchar_t* _in);

#define XA2W(x) XEvol_LocaleToUnicode(x)
#define XW2A(x) XEvol_UnicodeToLocale(x)

	const char*    XW2A_S(const wchar_t* _in, char* _out,size_t outlen);
	const wchar_t* XA2W_S(const char* _in, wchar_t* _out,size_t outlen);


	template <int _WCharWidth> wchar_t  TWCharTrait<_WCharWidth>::GetCodePoint(const wchar_t* _text , size_t& index , wchar_t* _out)
	{
		wchar_t _ret = _text[index];
		_out[0] = _ret;
		_out[1] = 0;
		index ++;
		return  _ret;
	}

	template <int _WCharWidth> wchar_t  TWCharTrait<_WCharWidth>::GetCodePoint(const wchar_t* _text , size_t& index )
	{
		wchar_t _ret = _text[index];
		index ++;
		return  _ret;
	}

	template <int _WCharWidth> size_t TWCharTrait<_WCharWidth>::strlen(const wchar_t* _text)
	{
		return wcslen(_text);
	}


	inline TWCharTrait<2>::UTF32  TWCharTrait<2>::GetCodePoint(const wchar_t* _text , size_t& index , wchar_t* _out)
	{
		return XEvol_GetUtf32CodePoint((const xWCharTrait::UTF16 *)_text , index , (xWCharTrait::UTF16*)_out );
	}

	inline TWCharTrait<2>::UTF32  TWCharTrait<2>::GetCodePoint(const wchar_t* _text , size_t& index )
	{
		return XEvol_GetUtf32CodePoint((const xWCharTrait::UTF16*)_text , index , NULL );
	}

	inline size_t TWCharTrait<2>::strlen(const wchar_t* _text)
	{
		return wcslen(_text);
	}

}
#endif

